package org.opens.javaskill.design;

/**
 * 功能:
 *      设计模式-桥接模式的demo.
 * 说明:
 *      1. DrawApi接口的实现是功能的实现部分.
 *      2. Shape2抽象类负责实现功能的抽象部分;
 *          - 这里的抽象的意思是: 不关注内部细节, 调用即可展示出`DrawApi接口的实现是功能的实现部分`的结果.
 */
public class BridgePattern {

    public static void main(String[] args) {
        Shape2 shape2 = new Circle2(new ReadCircle(), 12, 0, 0);
        Shape2 shape3 = new Circle2(new GreenCircle(), 22, 1, 1);
        System.out.println(shape2.draw());
        System.out.println(shape3.draw());
    }

}

interface DrawApi {
    String drawCircle(int radius, int x, int y);
}

class ReadCircle implements DrawApi {

    /**
     * 说明:
     *      1. 这里相当于是实现部分.
     */
    @Override
    public String drawCircle(int radius, int x, int y) {
        return String.format( "Circle-> color: red, radius: %d, x: %d, y: %d", radius, x, y );
    }

}

class GreenCircle implements DrawApi {

    /**
     * 说明:
     *      1. 这里也相当于是实现部分.
     */
    @Override
    public String drawCircle(int radius, int x, int y) {
        return String.format( "Circle-> color: green, radius: %d, x: %d, y: %d", radius, x, y );
    }

}

abstract class Shape2 {

    protected DrawApi drawApi;

    protected Shape2(DrawApi drawApi) {
        this.drawApi = drawApi;
    }

    /**
     * 说明:
     *      1. 这里相当于是`抽象部分`.
     */
    abstract String draw();

}

class Circle2 extends Shape2 {

    private Integer x;

    private Integer y;

    private Integer radius;

    public Circle2(DrawApi drawApi, Integer radius, Integer x, Integer y) {
        super(drawApi);
        this.radius = radius;
        this.x = x;
        this.y = y;
    }

    /**
     * 说明:
     *      1. 这里的这种方式使抽象与实现进行了分离.
     */
    @Override
    public String draw() {
        return this.drawApi.drawCircle(radius, x, y);
    }

    public Integer getX() {
        return x;
    }

    public void setX(Integer x) {
        this.x = x;
    }

    public Integer getY() {
        return y;
    }

    public void setY(Integer y) {
        this.y = y;
    }

    public Integer getRadius() {
        return radius;
    }

    public void setRadius(Integer radius) {
        this.radius = radius;
    }

}